/*************************************************************************
    > File Name: 1_event_tcp_server.c
    > Author: Ykk
    > Mail: 3393579535@qq.com 
    > Created Time: 2023年06月02日 星期五 15时24分41秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<event.h>
#include"network_utils.h"

#define PORT 8000
#define IP "192.168.152.129"
#define SIZE 1024

typedef struct FdEventMap
{
	int fd;
	struct event *ev;
}FdEvent;

FdEvent FdEv[SIZE];

void initFdEvArray()
{
	int i = 0;
	for(i = 0;i < SIZE;i++)
	{
		FdEv[i].fd = -1;
		FdEv[i].ev = NULL;
	}
}
int addEvent(int fd,struct event *ev)
{
	int i = 0;
	for(i = 0;i < SIZE;i++)
	{
		if(FdEv[i].fd < 0)
		{
			FdEv[i].fd = fd;
			FdEv[i].ev = ev;
			break;
		}
		if(i == SIZE)
		{
			printf("too many client...\n");
			return -1;
		}
	}
	return 0;
}
void destoryFdEvArray()
{
	int i = 0;
	for(i = 0;i < SIZE;i++)
	{
		if(FdEv[i].fd > 0&&FdEv[i].ev != NULL)
		{
			close(FdEv[i].fd);
			FdEv[i].fd = -1;
			event_free(FdEv[i].ev);
		}
	}
}
struct event *GetEvByFd(int fd)
{
	int i = 0;
	for(i = 0;i < SIZE;i++)
	{
		if(FdEv[i].fd == fd)
		{
			return FdEv[i].ev;
		}
	}
	return NULL;
}
void cfd_callback(int cfd,short event,void *arg)
{
	char buf[1500] = "";
	int n = Read(cfd,buf,sizeof(buf));
	if(n <= 0)
	{
		perror("err or close");
		//下树
		event_del(GetEvByFd(cfd));
		event_free(GetEvByFd(cfd));
		close(cfd);	
	}
	else
	{
		printf("%s\n",buf);
		Write(cfd,buf,n);
	}
}
void lfd_callback(int lfd,short event,void *arg)
{
	struct event_base * base = (struct event_base *)arg;

	int cfd = Accept(lfd,NULL,NULL);
	if(cfd > 0)
	{
		struct event *ev = event_new(base,cfd,EV_READ | EV_PERSIST,cfd_callback,NULL);
		event_add(ev,NULL);
		addEvent(cfd,ev);
	}
}

int main(int argc,char *argv[])
{
	initFdEvArray();
	//创建套接字
	//绑定
	int lfd = tcp4bind(PORT,IP);	
	//监听
	Listen(lfd,128);
	//创建event_base根节点
	struct event_base * base = event_base_new();
	//初始化lfd上树节点
	struct event *ev = event_new(base,lfd,EV_READ | EV_PERSIST,lfd_callback,base);
	//上树
	event_add(ev,NULL);
	//循环监听
	event_base_dispatch(base);//会阻塞
	//收尾
	close(lfd);
	destoryFdEvArray();
	event_base_free(base);
	return 0;
}
